#include "HexFileHelp.h"

#include <QDebug>

HexFileHelp::HexFileHelp()
{

}

///
/// \brief writeDataToHexFile
/// 把 data 数据 以Hex文件格式 写入到filename文件
/// 成功 返回true
/// \param filename
/// \param dataAddr     数据起始地址
/// \param mcuEntryAddr   mcu入口地址
/// \param data
/// \return
///
bool HexFileHelp::writeDataToHexFile(const QString &filename,
                                     quint32 dataAddr, quint32 mcuEntryAddr,
                                     const QByteArray &data)
{
    int totalbyte = data.count();
    if(totalbyte<1) return false;

    QFile file(filename);

    quint32 hi_dataAddr=dataAddr>>16,lo_dataAddr=dataAddr & 0x0FFFF; //高低16位
    quint32 header;
    QString str;
//    QByteArray bt;

    //创建并打开文件
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) return false;
    file.seek(0);

    QTextStream out(&file);

    //写入数据起始地址
    header=0x02000004;
    str=QString("%1").arg(header,8,16,QChar('0'));
    str=str + QString("%1").arg(hi_dataAddr,4,16,QChar('0'));
    str.append(calcBytesSumCheck(str));
    out<<':'<<str.toUpper()<<'\n';

    //写入数据
    quint32 colcnt=0;
    const unsigned char *pd = reinterpret_cast<const unsigned char *>(data.data());
    bool onelineok=false;   //可以写入一行了
    str.clear();
    for (int i = 0; i < totalbyte; ++i) {
        str = str + QString("%1").arg(pd[i],2,16,QChar('0'));
        colcnt++;
        if(colcnt==16 || i == totalbyte-1 || (lo_dataAddr+colcnt)>=0x010000){
            onelineok=true;
        }

        if(onelineok){
            onelineok=false;
            //添加头部信息
//            qDebug()<<str;
            str.prepend("00");
            str.prepend(
//                        QString("%11%2200")  //由于arg函数是 %0~%99的 所以占满两位 保证后面的两个 00能正常见添加
                        QString("%1%2")
                        .arg(colcnt,2,16,QChar('0'))
                        .arg(lo_dataAddr,4,16,QChar('0'))
                        );
            str.append(calcBytesSumCheck(str));
//            qDebug()<<str;
            out<<':'<<str.toUpper()<<'\n';  //写入一行数据

            if((lo_dataAddr+colcnt)>=0x010000 && i<(totalbyte-1)){
                //写入数据起始地址
                hi_dataAddr++;
                header=0x02000004;
                str=QString("%1").arg(header,8,16,QChar('0'));
                str=str + QString("%1").arg(hi_dataAddr,4,16,QChar('0'));
                str.append(calcBytesSumCheck(str));
                out<<':'<<str.toUpper()<<'\n';
            }

            lo_dataAddr=(lo_dataAddr + colcnt) & 0x0FFFF;

            colcnt=0;
            str.clear();
        }

    }

    //写mcu运行的入口地址
    header = 0x04000005;
    str=QString("%1").arg(header,8,16,QChar('0'));
    str=str + QString("%1").arg(mcuEntryAddr,8,16,QChar('0'));
    str.append(calcBytesSumCheck(str));
    out<<':'<<str.toUpper()<<'\n';


    // 写文件结束
    out<<":00000001FF\n";

    file.close();

    return true;
}


///
/// \brief calcBytesSumCheck
/// 将data所有数据求和 取最低8位 b 返回(0x100-b)的低8位
/// \param data
/// \return
///
QString HexFileHelp::calcBytesSumCheck(const QString &data)
{
    QString res="00";
    unsigned char sum=0;
    int cnt = data.size()/2;

    for (int i = 0; i < cnt; ++i) {
        sum=sum +
                static_cast<unsigned char>(
                    0x0FF & data.mid(i*2,2).toUInt(nullptr,16)
                    );

    }

    sum=static_cast<unsigned char>(0x0FF & (0x0100-sum));
    res=QString("%1").arg(sum,2,16,QChar('0'));
    return res;
}
